/**

This file is part of MaCI/GIMnet.

MaCI/GIMnet is free software: you can redistribute it and/or modify it 
under the terms of the GNU Lesser General Public License as published 
by the Free Software Foundation, either version 3 of the License, or 
(at your option) any later version.

MaCI/GIMnet is distributed in the hope that it will be useful, but WITHOUT 
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public 
License for more details.

You should have received a copy of the GNU Lesser General Public 
License along with GIMnet. (See COPYING.LESSER) If not, see 
<http://www.gnu.org/licenses/>.

**/
/**
 *
 * $Id: GIMNotifierMessage.hpp,v 1.2 2009-02-09 11:15:58 amaula Exp $
 *
 */
#ifndef _GIMNOTIFIERMESSAGE_HPP_
#define _GIMNOTIFIERMESSAGE_HPP_
#include <string>
#include "bitestream.h"


class CGIMNotifierMessage
{
public:
  CGIMNotifierMessage() 
    : iDirty(true),
      iPriority(0),
      iSender(),
      iTitle(),
      iBody(),
      iBSData(NULL) {}
  
  CGIMNotifierMessage(const int aPriority, 
		      const std::string aSender, 
		      const std::string aTitle, 
		      const std::string aBody)
    : iDirty(true),
      iPriority(aPriority),
      iSender(aSender),
      iTitle(aTitle),
      iBody(aBody),
      iBSData(NULL) {}
  
  CGIMNotifierMessage(const char *aBSData, const unsigned int aBSDataSize) 
    : iDirty(true),
      iPriority(0),
      iSender(),
      iTitle(),
      iBody(),
      iBSData(NULL) {
    SetMsgData(aBSData, aBSDataSize);
  }
  
  ~CGIMNotifierMessage() {
    if (iBSData != NULL) bsFree(iBSData);
  }
  
  bool SetMsgData(const char *aBSData, const unsigned int aBSDataSize) {
    bool result = false;
    if (aBSDataSize >= sizeof(bsStreamHeader)) {
      iBSData = bsDecode(const_cast<char *>(aBSData));
      if (iBSData != NULL) {
	int stage = 0;
	bsTag *tag = bsNextTag(iBSData);
	while (tag) {
	  // At this point we know that 'tag' is ok.
	  if (tag->tag == BS_NAMED) {
	    if (tag->name == std::string("prio")) {
	      iPriority = tag->value;
	      stage |= 1<<0;

	    } else if (tag->name == std::string("title")) {
	      iTitle = tag->string;
	      stage |= 1<<1;

	    } else if (tag->name == std::string("sender")) {
	      iSender = tag->string;
	      stage |= 1<<2;

	    } else if (tag->name == std::string("body")) {
	      iBody = tag->string;
	      stage |= 1<<3;
	      
	    } else {
	      dPrint(3,"Unidentified tag name '%s'! Skip.", tag->name);
	    }
	  } else {
	    dPrint(3,"Unnamed tag received! (Tag was %d) Skip this message.", 
		   tag->tag);
	  }
	  
	  // next
	  tag = bsNextTag(iBSData);
	}

	// Tsek that we have all the fields present (atleast once :)
	if ((stage == 1)<<0 | 1<<1 | 1<<2 | 1<<3) {
	  dPrint(6,"All fields present. Proceed.");
	  result = true;

	} else {
	  dPrint(3,"Incomplete BiteStream for GIMNotifierMessage!");
	  
	}
	
      }
    }
    return result;
  }

  bool GetMsgData(const char **aBSDataPtr, int *aBSDataSizePtr) {
    bool result = false;

    if (iDirty) {
      // Allocate the bs if necessary, otherwise clear it.
      if (iBSData == NULL) {
	iBSData = bsAlloc();
	assert(iBSData != NULL);

      } else {
	bsClear(iBSData);

      }

      // Now, assign data.
      bsAddNamedInt(iBSData, "prio", iPriority);
      bsAddNamedStr(iBSData, "title", iTitle.c_str());
      bsAddNamedStr(iBSData, "sender", iSender.c_str());
      bsAddNamedStr(iBSData, "body", iBody.c_str());

      // Finalize
      bsFinalize(iBSData);

      // No longer dirty
      iDirty = false; 
    }
    
    // Copy the data.
    *aBSDataPtr = iBSData->buf;
    *aBSDataSizePtr = iBSData->length;

    result = true;
    return result;
  }  
  
  
  int GetPriority(void) const {
    return iPriority;
  }
  const std::string &GetSender(void) const { 
    return iSender;
  }
  const std::string &GetTitle(void) const { 
    return iTitle;
  }
  const std::string &GetBody(void) const { 
    return iBody;
  }

  void SetPriority(const int aPriority) {
    iPriority = aPriority;
    iDirty = true;
  }

  void SetSender(const std::string &aSender) {
    iSender = aSender;
    iDirty = true;
  }

  void SetTitle(const std::string &aTitle) {
    iTitle = aTitle;
    iDirty = true;
  }

  void SetBody(const std::string &aBody) {
    iBody = aBody;
    iDirty = true;
  }
  
protected:  
  bool iDirty;  ///< Is BSData in sync with fields?
  int iPriority; ///< Message level (follows dPrint style)
  std::string iSender; ///< Sender name
  std::string iTitle; ///< Message title
  std::string iBody; ///< Message body
  
  BiteStream *iBSData; ///< Bitestream formatted data is stored here

private:
  CGIMNotifierMessage(const CGIMNotifierMessage &)    
    : iDirty(true),
      iPriority(0),
      iSender(),
      iTitle(),
      iBody(),
      iBSData(NULL) {}
  CGIMNotifierMessage &operator =(CGIMNotifierMessage &) { return *this; }
  
};

#endif
